# Copyright The IETF Trust 2013-2020, All Rights Reserved
# -*- coding: utf-8 -*-


# utilities for constructing agendas for IESG telechats

import datetime
from collections import OrderedDict

from django.conf import settings
from django.http import Http404

import debug                            # pyflakes:ignore

from ietf.doc.models import Document, LastCallDocEvent, ConsensusDocEvent
from ietf.doc.utils_search import fill_in_telechat_date
from ietf.iesg.models import TelechatDate, TelechatAgendaItem, TelechatAgendaContent
from ietf.review.utils import review_assignments_to_list_for_docs
from ietf.utils.timezone import date_today, make_aware

def get_agenda_date(date=None):
    if not date:
        try:
            return TelechatDate.objects.active().order_by('date')[0].date
        except IndexError:
            return date_today()
    else:
        parsed_date = make_aware(datetime.datetime.strptime(date, "%Y-%m-%d"), settings.TIME_ZONE).date()
        try:
            return TelechatDate.objects.active().get(date=parsed_date).date
        except (ValueError, TelechatDate.DoesNotExist):
            raise Http404

def get_doc_section(doc):
    if doc.type_id == 'draft':
        if doc.intended_std_level_id in ["bcp", "ds", "ps", "std"]:
            s = "2"
        else:
            s = "3"

        g = doc.group_acronym()
        if g and str(g) != 'none':
            s += ".1"
        elif s == "3" and doc.stream_id in ("ise","irtf"):
            s += ".3"
        else:
            s += ".2"
        if doc.get_state_slug() != "rfc" and doc.get_state_slug('draft-iesg') not in ("lc", "writeupw", "goaheadw", "iesg-eva", "defer", "approved", "ann", "rfcqueue", "pub"):
            s += ".3"
        elif doc.returning_item():
            s += ".2"
        else:
            s += ".1"

    elif doc.type_id == 'charter':
        s = "4"
        if doc.group.state_id in ('active', 'dormant'):
            s += ".2"
        else:
            s += ".1"
        if doc.get_state_slug() in ('extrev', 'iesgrev'):
            s += '.2'
        else:
            s += '.1'

    elif doc.type_id == 'statchg':
        protocol_action = False
        for relation in doc.relateddocument_set.filter(relationship__slug__in=('tops','tois','tohist','toinf','tobcp','toexp')):
            if relation.relationship_id in ('tops','tois') or relation.target.std_level_id in ('std','ds','ps'):
                protocol_action = True
        if protocol_action:
            s = "2.3"
        else:
            s = "3.3"
        if doc.get_state_slug() not in ("iesgeval", "defer", "appr-pr", "appr-pend", "appr-sent"):
            s += ".3"
        elif doc.returning_item():
            s += ".2"
        else:
            s += ".1"

    elif doc.type_id == 'conflrev':
        if not doc.get_state('conflrev') or doc.get_state('conflrev').slug not in ('adrev','iesgeval','appr-reqnopub-pend','appr-reqnopub-sent','appr-noprob-pend','appr-noprob-sent','defer'):
             s = "3.4.3"
        elif doc.returning_item():
             s = "3.4.2"
        else:
             s = "3.4.1"

    return s

def agenda_sections():
    return OrderedDict([
        ('1', {'title':"Administrivia"}),
        ('1.1', {'title':"Roll call"}),
        ('1.2', {'title':"Bash the agenda"}),
        ('1.3', {'title':"Approval of the minutes of past telechats"}),
        ('1.4', {'title':"List of remaining action items from last telechat"}),
        ('2', {'title':"Protocol actions"}),
        ('2.1', {'title':"WG submissions"}),
        ('2.1.1', {'title':"New items", 'docs': []}),
        ('2.1.2', {'title':"Returning items", 'docs':[]}),
        ('2.1.3', {'title':"For action", 'docs':[]}),
        ('2.2', {'title':"Individual submissions"}),
        ('2.2.1', {'title':"New items", 'docs':[]}),
        ('2.2.2', {'title':"Returning items", 'docs':[]}),
        ('2.2.3', {'title':"For action", 'docs':[]}),
        ('2.3', {'title':"Status changes"}),
        ('2.3.1', {'title':"New items", 'docs':[]}),
        ('2.3.2', {'title':"Returning items", 'docs':[]}),
        ('2.3.3', {'title':"For action", 'docs':[]}),
        ('3', {'title':"Document actions"}),
        ('3.1', {'title':"WG submissions"}),
        ('3.1.1', {'title':"New items", 'docs':[]}),
        ('3.1.2', {'title':"Returning items", 'docs':[]}),
        ('3.1.3', {'title':"For action", 'docs':[]}),
        ('3.2', {'title':"Individual submissions via AD"}),
        ('3.2.1', {'title':"New items", 'docs':[]}),
        ('3.2.2', {'title':"Returning items", 'docs':[]}),
        ('3.2.3', {'title':"For action", 'docs':[]}),
        ('3.3', {'title':"Status changes"}),
        ('3.3.1', {'title':"New items", 'docs':[]}),
        ('3.3.2', {'title':"Returning items", 'docs':[]}),
        ('3.3.3', {'title':"For action", 'docs':[]}),
        ('3.4', {'title':"IRTF and Independent Submission stream documents"}),
        ('3.4.1', {'title':"New items", 'docs':[]}),
        ('3.4.2', {'title':"Returning items", 'docs':[]}),
        ('3.4.3', {'title':"For action", 'docs':[]}),
        ('4', {'title':"Working Group actions"}),
        ('4.1', {'title':"WG creation"}),
        ('4.1.1', {'title':"Proposed for IETF review", 'docs':[]}),
        ('4.1.2', {'title':"Proposed for approval", 'docs':[]}),
        ('4.2', {'title':"WG rechartering"}),
        ('4.2.1', {'title':"Under evaluation for IETF review", 'docs':[]}),
        ('4.2.2', {'title':"Proposed for approval", 'docs':[]}),
        ('5', {'title':"IAB news we can use"}),
        ('6', {'title':"Management issues"}),
        ('7', {'title':"Any Other Business (WG News, New Proposals, etc.)"}),
        ])

def fill_in_agenda_administrivia(date, sections):
    extra_info = (
        ("1.1", "roll_call"),
        ("1.3", "minutes"),
        ("1.4", "action_items"),
    )

    for s, key in extra_info:
        try:
            text = TelechatAgendaContent.objects.get(section__slug=key).text
        except TelechatAgendaContent.DoesNotExist:
            text = ""
        sections[s]["text"] = text

def fill_in_agenda_docs(date, sections, docs=None):
    if not docs:
        docs = Document.objects.filter(docevent__telechatdocevent__telechat_date=date)
        docs = docs.select_related("stream", "group").distinct()
        fill_in_telechat_date(docs)

    review_assignments_for_docs = review_assignments_to_list_for_docs(docs)

    for doc in docs:
        if doc.telechat_date() != date:
            continue

        if not hasattr(doc, 'balloting_started'):
            e = doc.latest_event(type="started_iesg_process")
            doc.balloting_started = e.time if e else datetime.datetime.min

        if doc.type_id == "draft":
            s = doc.get_state("draft-iana-review")
            if s: # and s.slug in ("not-ok", "changed", "need-rev"):
                doc.iana_review_state = str(s)

            if doc.get_state_slug("draft-iesg") == "lc":
                e = doc.latest_event(LastCallDocEvent, type="sent_last_call")
                if e:
                    doc.lastcall_expires = e.expires

            if doc.stream_id in ("ietf", "irtf", "iab"):
                doc.consensus = "Unknown"
                e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
                if e and (e.consensus != None):
                    doc.consensus = "Yes" if e.consensus else "No"

            doc.review_assignments = review_assignments_for_docs.get(doc.name, [])
        elif doc.type_id == "conflrev":
            doc.conflictdoc = doc.relateddocument_set.get(relationship__slug='conflrev').target
        elif doc.type_id == "charter":
            pass

        number = get_doc_section(doc)
        if number: #  and num in sections
            sections[number]["docs"].append(doc)

    # prune empty "For action" sections
    empty_for_action = [n for n, section in sections.items()
                        if section["title"] == "For action" and not section["docs"]]
    for num in empty_for_action:
        del sections[num]

    # Be careful to keep this the same as what's used in agenda_documents
    for s in sections.values():
        if "docs" in s:
            s["docs"].sort(key=lambda d: d.balloting_started)

def fill_in_agenda_management_issues(date, sections):
    s = "6.%s"
    for i, item in enumerate(TelechatAgendaItem.objects.filter(type=3).order_by('id'), start=1):
        sections[s % i] = { "title": item.title, "text": item.text }

def agenda_data(date=None):
    """Return a dict with the different IESG telechat agenda components."""
    date = get_agenda_date(date)
    sections = agenda_sections()

    fill_in_agenda_administrivia(date, sections)
    fill_in_agenda_docs(date, sections)
    fill_in_agenda_management_issues(date, sections)

    return { 'date': date.isoformat(), 'sections': sections }
